package edu.chalmers.targine;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;

public class Billboard {
	public float x, y, z;
	public float xRot, yRot, zRot;
	public float scale;
	public int texID;
	private FloatBuffer vertexBuffer;	// buffer holding the vertices
	private FloatBuffer textureBuffer;	// buffer holding the texture coordinates
	private boolean visible = true;
	
	public Billboard(int texID, float x, float y, float z, float scale, float xRot){
		this.texID = texID;
		this.x = x;
		this.y = y;
		this.z = z;
		this.scale = scale;
		this.xRot = xRot;
//		xRot = yRot = zRot = 0f;
		
		initBillboard();
	}
	
	private void initBillboard(){
		float vertices[] = {
				-1.0f, -1.0f,  0.0f,		// V1 - bottom left
				-1.0f,  1.0f,  0.0f,		// V2 - top left
				 1.0f, -1.0f,  0.0f,		// V3 - bottom right
				 1.0f,  1.0f,  0.0f			// V4 - top right
		};

		float texture[] = {
				// Mapping coordinates for the vertices
				0.0f, 1.0f,		// top left		(V2)
				0.0f, 0.0f,		// bottom left	(V1)
				1.0f, 1.0f,		// top right	(V4)
				1.0f, 0.0f		// bottom right	(V3)
		};
		
		// a float has 4 bytes so we allocate for each coordinate 4 bytes
		ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length * 4);
		byteBuffer.order(ByteOrder.nativeOrder());
		vertexBuffer = byteBuffer.asFloatBuffer();
		vertexBuffer.put(vertices);
		vertexBuffer.position(0);

		byteBuffer = ByteBuffer.allocateDirect(texture.length * 4);
		byteBuffer.order(ByteOrder.nativeOrder());
		textureBuffer = byteBuffer.asFloatBuffer();
		textureBuffer.put(texture);
		textureBuffer.position(0);
	}
	
	public void draw(GL10 gl){
		if(visible){
			float[] modelview = new float[16];
			int i, j;
			
			// save the current modelview matrix
			gl.glPushMatrix();
			// get the current modelview matrix
			((GL11)gl).glGetFloatv(GL11.GL_MODELVIEW_MATRIX, modelview, 0);
			// undo all rotations, beware all scaling is lost as well 
			for( i=0; i<3; i++ ){
				for( j=0; j<3; j++ ){
					if ( i==j ){
						modelview[i*4+j] = 1.0f;
					} else{
						modelview[i*4+j] = 0.0f;
					}
				}
			}
			// set the modelview with no rotations and scaling
			gl.glLoadMatrixf(modelview, 0);
			
			gl.glTranslatef(x, y, z);
			gl.glScalef(scale, scale, scale);
			gl.glRotatef(xRot, 0, 0, 1);
	
			//fix for tex being dark?
	        gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_REPLACE);
			//enable png transparency
	        gl.glEnable(GL10.GL_BLEND);
	//        gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);
	        gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
			/** The draw method for the square with the GL context */
			gl.glEnable(GL10.GL_TEXTURE_2D);
			// bind the previously generated texture
			gl.glBindTexture(GL10.GL_TEXTURE_2D, texID);
					
			gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
			gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
	
			// Point to our vertex buffer
			gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
			gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
	
			// Draw the vertices as triangle strip
			gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
	
			//Disable the client state before leaving
			gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
			gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
			gl.glDisable(GL10.GL_BLEND);
			
			// restores the modelview matrix
			gl.glPopMatrix();
		}
	}
	
	public void setVisible(boolean visible){
		this.visible = visible;
	}
}
